package engine

import (
	"encoding/json"
	"net/http"
	"time"

	"gitcode.com/eteam/sae.git/storage"
	"gitcode.com/eteam/sae.git/types"
	"github.com/gin-contrib/sse"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"github.com/redis/go-redis/v9"
)

func (sae *SimpleAgentEngine) listTask(ctx *gin.Context) {
	userInfo, err := sae.cfg.AuthProvider.GetUserInfo(ctx.Request)
	if err != nil {
		ctx.String(403, err.Error())
		return
	}
	var req ListTaskRequest
	err = ctx.BindQuery(&req)
	if err != nil {
		return
	}
	count, err := sae.cfg.StorageHandle.TaskInfoDao.CountByOwnerId(ctx, userInfo.UserId)
	if err != nil {
		ctx.String(500, err.Error())
		return
	}
	taskItemList, err := sae.cfg.StorageHandle.TaskInfoDao.ListByOwnerId(ctx, userInfo.UserId, int64(req.Offset), int64(req.Limit))
	if err != nil {
		ctx.String(500, err.Error())
		return
	}
	taskList := []*types.Task{}
	for _, taskItem := range taskItemList {
		taskList = append(taskList, taskItem.ToTask())
	}

	ctx.JSON(200, &ListTaskResponse{
		TotalCount: count,
		TaskList:   taskList,
	})
}

func (sae *SimpleAgentEngine) getTaskData(ctx *gin.Context) {
	userInfo, err := sae.cfg.AuthProvider.GetUserInfo(ctx.Request)
	if err != nil {
		ctx.String(403, err.Error())
		return
	}
	taskId := ctx.Param("taskId")
	var req GetTaskDataRequest
	err = ctx.BindQuery(&req)
	if err != nil {
		return
	}
	taskItem, err := sae.cfg.StorageHandle.TaskInfoDao.Get(ctx, taskId)
	if err != nil {
		ctx.String(500, err.Error())
		return
	}
	if taskItem.OwnerId != userInfo.UserId {
		ctx.String(403, "没有访问权限")
		return
	}
	task := taskItem.ToTask()

	if req.WithMessage {
		msgItemList, err := sae.cfg.StorageHandle.MessageInfoDao.ListByTask(ctx, []string{taskId})
		if err != nil {
			ctx.String(500, err.Error())
			return
		}
		for _, msgItem := range msgItemList {
			task.Messages = append(task.Messages, *msgItem.ToMessage())
		}
	}
	if req.WithArtifact {
		artifactItemList, err := sae.cfg.StorageHandle.ArtifactInfoDao.ListByTask(ctx, []string{taskId})
		if err != nil {
			ctx.String(500, err.Error())
			return
		}
		for _, artifactItem := range artifactItemList {
			task.Artifacts = append(task.Artifacts, *artifactItem.ToArtifact())
		}
	}
	if req.WithFormDefine {
		formDefineItemList, err := sae.cfg.StorageHandle.FormDefineInfoDao.ListByTask(ctx, []string{taskId})
		if err != nil {
			ctx.String(500, err.Error())
			return
		}
		for _, formDefineItem := range formDefineItemList {
			task.FormDefines = append(task.FormDefines, *formDefineItem.ToFormDefine())
		}
	}
	ctx.JSON(200, task)
}

func (sae *SimpleAgentEngine) createTask(ctx *gin.Context) {
	userInfo, err := sae.cfg.AuthProvider.GetUserInfo(ctx.Request)
	if err != nil {
		ctx.String(403, err.Error())
		return
	}
	var req CreateTaskRequest
	err = ctx.BindJSON(&req)
	if err != nil {
		return
	}
	skillProvider := sae.findSkillProvider(req.SkillId)
	if skillProvider == nil {
		ctx.String(500, "no skill provider find")
		return
	}

	taskId := uuid.NewString()
	nowTime := time.Now().UnixMilli()
	//创建task
	taskInfoItem := &storage.TaskInfoDbItem{
		TaskId:  taskId,
		OwnerId: userInfo.UserId,
		Status: storage.TaskStatusDbItem{
			State: types.TaskCreateed,
			Message: storage.TaskStatusMessageDbItem{
				MessageId: uuid.NewString(),
				TimeStamp: nowTime,
				Role:      "agent",
				Parts: []types.Part{
					{
						TextPart: &types.TextPart{
							Text: "任务创建成功",
						},
					},
				},
			},
			TimeStamp: nowTime,
		},
		SkillId: req.SkillId,
	}
	err = sae.cfg.StorageHandle.TaskInfoDao.Insert(ctx, taskInfoItem)
	if err != nil {
		ctx.JSON(500, err.Error())
		return
	}
	handler := newTaskHandlerImpl(ctx, taskId, sae.cfg.StorageHandle)
	failStatus := &storage.TaskStatusDbItem{
		State: types.TaskFailed,
		Message: storage.TaskStatusMessageDbItem{
			MessageId: uuid.NewString(),
			TimeStamp: time.Now().UnixMilli(),
			Role:      types.AgentMessageRole,
			Parts: []types.Part{
				{
					TextPart: &types.TextPart{
						Text: "任务执行失败",
					},
				},
			},
		},
		TimeStamp: time.Now().UnixMilli(),
	}
	err = skillProvider.OnInit(handler)
	if err != nil {
		handler.UpdateTaskStatus(failStatus) //skip error check
		ctx.JSON(500, err.Error())
		return
	}
	if len(req.Message.Parts) > 0 {
		err = sae.cfg.StorageHandle.MessageInfoDao.Insert(ctx, &storage.MessageInfoDbItem{
			MessageId: req.Message.MessageId,
			TaskId:    taskId,
			TimeStamp: nowTime,
			Role:      req.Message.Role,
			Parts:     req.Message.Parts,
		})
		if err != nil {
			handler.UpdateTaskStatus(failStatus) //skip error check
			ctx.JSON(500, err.Error())
			return
		}
		err = skillProvider.OnMessage(userInfo.UserId, userInfo.UserRole, taskInfoItem, handler, ctx.Request)
		if err != nil {
			handler.UpdateTaskStatus(failStatus) //skip error check
			ctx.JSON(500, err.Error())
			return
		}
	}
	ctx.JSON(200, &CreateTaskResponse{
		TaskId: taskId,
	})
}

func (sae *SimpleAgentEngine) processTaskMessage(ctx *gin.Context) {
	userInfo, err := sae.cfg.AuthProvider.GetUserInfo(ctx.Request)
	if err != nil {
		ctx.String(403, err.Error())
		return
	}
	taskId := ctx.Param("taskId")
	var msg types.Message
	err = ctx.BindJSON(&msg)
	if err != nil {
		return
	}
	//检测task状态
	taskInfoItem, err := sae.cfg.StorageHandle.TaskInfoDao.Get(ctx, taskId)
	if err != nil {
		ctx.String(500, "任务不存在")
		return
	}
	if taskInfoItem.OwnerId != userInfo.UserId {
		ctx.String(500, "缺少访问权限")
		return
	}
	//检查任务是否处于input-required
	if taskInfoItem.Status.State != types.TaskInputRequired {
		ctx.String(500, "无效的输入")
		return
	}

	skillProvider := sae.findSkillProvider(taskInfoItem.SkillId)
	if skillProvider == nil {
		ctx.String(500, "no skill provider find")
		return
	}

	err = sae.cfg.StorageHandle.MessageInfoDao.Insert(ctx, &storage.MessageInfoDbItem{
		MessageId: msg.MessageId,
		TaskId:    taskId,
		TimeStamp: time.Now().UnixMilli(),
		Role:      msg.Role,
		Parts:     msg.Parts,
	})
	if err != nil {
		ctx.JSON(500, err.Error())
		return
	}

	handler := newTaskHandlerImpl(ctx, taskId, sae.cfg.StorageHandle)
	failStatus := &storage.TaskStatusDbItem{
		State: types.TaskFailed,
		Message: storage.TaskStatusMessageDbItem{
			MessageId: uuid.NewString(),
			TimeStamp: time.Now().UnixMilli(),
			Role:      types.AgentMessageRole,
			Parts: []types.Part{
				{
					TextPart: &types.TextPart{
						Text: "任务执行失败",
					},
				},
			},
		},
		TimeStamp: time.Now().UnixMilli(),
	}

	err = skillProvider.OnMessage(userInfo.UserId, userInfo.UserRole, taskInfoItem, handler, ctx.Request)
	if err != nil {
		handler.UpdateTaskStatus(failStatus) //skip error check
		ctx.JSON(500, err.Error())
		return
	}
	ctx.JSON(200, map[string]any{})
}

func (sae *SimpleAgentEngine) watchTaskEvent(ctx *gin.Context) {
	userInfo, err := sae.cfg.AuthProvider.GetUserInfo(ctx.Request)
	if err != nil {
		ctx.String(403, err.Error())
		return
	}
	taskId := ctx.Param("taskId")
	//检测task状态
	taskInfoItem, err := sae.cfg.StorageHandle.TaskInfoDao.Get(ctx, taskId)
	if err != nil {
		ctx.String(500, "任务不存在")
		return
	}
	if taskInfoItem.OwnerId != userInfo.UserId {
		ctx.String(500, "缺少访问权限")
		return
	}

	sub := sae.cfg.StorageHandle.EventDao.Subscribe(ctx, taskId)
	defer sub.Close()

	setHeader := false
	for {
		evMsg, err := sub.ReceiveTimeout(ctx, 1*time.Minute)
		if err != nil {
			return
		}
		_, ok := evMsg.(*redis.Message)
		if !ok {
			continue
		}
		if !setHeader {
			setHeader = true
			ctx.Header("Content-Type", sse.ContentType)
			ctx.Header("Cache-Control", "no-cache")
			ctx.Header("Connection", "keep-alive")
			ctx.Writer.WriteHeader(-1)
		}
		err = sae.processSse(ctx.Writer, evMsg.(*redis.Message))
		if err != nil {
			return
		}
		ctx.Writer.Flush()
	}
}

type ObjectKindWrap struct {
	Kind types.ObjectKind `json:"kind"`
}

func (sae *SimpleAgentEngine) processSse(writer http.ResponseWriter, evMsg *redis.Message) error {
	kindWrap := &ObjectKindWrap{}
	err := json.Unmarshal([]byte(evMsg.Payload), kindWrap)
	if err != nil {
		return err
	}
	if kindWrap.Kind == types.MessageObjectKind {
		obj := &types.Message{}
		err = json.Unmarshal([]byte(evMsg.Payload), obj)
		if err != nil {
			return err
		}
		err = sse.Encode(writer, sse.Event{
			Id:    obj.MessageId,
			Event: string(kindWrap.Kind),
			Data:  evMsg.Payload,
		})
		if err != nil {
			return err
		}
	} else if kindWrap.Kind == types.TaskStatusUpdateObjectKind {
		obj := &types.TaskStatusUpdateEvent{}
		err = json.Unmarshal([]byte(evMsg.Payload), obj)
		if err != nil {
			return err
		}
		err = sse.Encode(writer, sse.Event{
			Id:    uuid.NewString(),
			Event: string(kindWrap.Kind),
			Data:  evMsg.Payload,
		})
		if err != nil {
			return err
		}
	} else if kindWrap.Kind == types.TaskArtifactUpdateObjectKind {
		obj := &types.TaskArtifactUpdateEvent{}
		err = json.Unmarshal([]byte(evMsg.Payload), obj)
		if err != nil {
			return err
		}
		err = sse.Encode(writer, sse.Event{
			Id:    obj.Artifact.ArtifactId,
			Event: string(kindWrap.Kind),
			Data:  evMsg.Payload,
		})
		if err != nil {
			return err
		}
	} else if kindWrap.Kind == types.TaskFormDefineUpdateObjectKind {
		obj := &types.TaskFormDefineUpdateEvent{}
		err = json.Unmarshal([]byte(evMsg.Payload), obj)
		if err != nil {
			return err
		}
		err = sse.Encode(writer, sse.Event{
			Id:    obj.FormDefine.FormDefineId,
			Event: string(kindWrap.Kind),
			Data:  evMsg.Payload,
		})
		if err != nil {
			return err
		}
	}
	return nil
}
